<?php

class WorkflowService extends FServiceBase
{    
    /**
    * Get a Workflow model given its ID
    * 
    * @param int id Workflow ID
    * @return FServiceModel
    */
    public function get($params){
        $model = Workflow::model()->findByPk($this->getParam($params, 'id',0));
        if (! $model)
            $this->result->fail(ERROR_INVALID_DATA, Yii::t('Cms.Workflow','Invalid ID.'));
        $this->result->processed('model', $model);
        return $this->result;
    }
    
    public function save($params) {
        $model = $this->getModel($params['Workflow'],'Workflow');
        $sameWorkflowId = $this->getParam($params, 'same_workflow', 0);
        
        $isUpdate = (boolean) $model->id;
        $this->result->processed('model', $model);
        //check is auto create Live state
        //url not required
        $auto = $this->getParam($params, 'auto', false);
        if ($auto)
            $model->setScenario('auto');
        
        if (! $model->validate())
            $this->result->fail(ERROR_INVALID_DATA, Yii::t('Cms.Workflow', 'Submitted data is missing or invalid.'));
        elseif ($this->getParam($params, 'validateOnly',0) == TRUE)
            return $this->result;
        elseif (! $model->save(false))
            $this->result->fail(ERROR_HANDLING_DB, Yii::t('Cms.Workflow','Error while saving submitted data into database.'));
        elseif ($isUpdate == false)
        {
            //active page in this workflow same specail workflow exist
            if ($sameWorkflowId)
            {
                $command = Yii::app()->getDb()->createCommand();
                $rows = $command->select()
                    ->from(SITE_TABLE_PREFIX.'page_current_revision')
                    ->where('workflow_id=:id', array(':id'=>$sameWorkflowId))
                    ->queryAll();
                if (count($rows))
                {
                    foreach ($rows as $row)
                    {
                        $command->reset();
                        $exist = $command->select('COUNT(*)')
                            ->from(SITE_TABLE_PREFIX.'page_current_revision')
                            ->where('page_id=:page_id AND revision=:revision AND workflow_id=:workflow_id',
                                array(
                                    ':page_id'=>(int) $row['page_id'],
                                    ':revision'=>$row['revision'],
                                    ':workflow_id'=>$model->id,
                                )
                            )
                            ->queryScalar();
                        if (!$exist)
                        {
                            $command->insert(SITE_TABLE_PREFIX.'page_current_revision', array(
                                'page_id'=>$row['page_id'],
                                'revision'=>$row['revision'],
                                'workflow_id'=>$model->id,
                            ));
                        }
                    }
                }
            }
            elseif ($model->type == Workflow::TYPE_INITITAL || $model->type == Workflow::TYPE_FINAL)
                FSM::_run('Cms.page.initCurrentByWorkflow', array('workflow_id'=>$model->id,'site_id'=>$model->site_id));
        }
        
        return $this->result;
    }


    public function delete($params) {
        $ids = $this->getParam($params, 'ids', array());
        $force = $this->getParam($params, 'force', false);
        if ($ids == 0) {
            return $this->result->fail(ERROR_INVALID_DATA, Yii::t('Cms.Workflow','Invalid ID.'));
        }
      
        if (!is_array($ids)) $ids = array($ids);
        foreach($ids as $id) {
            $model = Workflow::model()->findByPk($id);
            if ($model->name != 'Live' || $force = true) {
                try {
                    $model->delete();
                    FSM::_run('Cms.page.deleteCurrentByWorkflow', array('workflow_id'=>$id));
                } catch (CDbException $ex) {
                    $this->result->fail(ERROR_HANDLING_DB, $ex->getMessage());
                }
            } else
                $this->result->fail(ERROR_INVALID_DATA, Yii::t('Cms.Workflow','Not allow delete Live State.'));
        }
        return $this->result;
    }
    
    /**
    * TODO: check any where use
    * 
    * @param mixed $params
    * @return FServiceModel
    */
    /*public function getList($params)
    {
        $siteId = $this->getParam($params, 'site_id', 0);
        $id = $this->getParam($params, 'id', 0);
        //use to find next state
        $previousId = $this->getParam($params, 'previous', 0);
        $nextId = $this->getParam($params, 'next', 0);
        if ($siteId <= 0) {
            //$this->result->fail(ERROR_INVALID_DATA, Yii::t('Cms.Workflow','Invalid Site ID.'));
            $this->result->processed('models', array());
            return $this->result;
        }
        $criteria = new CDbCriteria();
        $criteria->compare('site_id', $siteId);
        if ($id)
            $criteria->compare('id', '<> '.$id);
        if ($previousId) {
            $previousIds = $this->findWorkflowIds($previousId, 'previous', true);
            $previousIds[] = $previousId;
            $criteria->addNotInCondition('id', $previousIds);
        } elseif ($nextId) {
            $nextIds = $this->findWorkflowIds($nextId, 'next', true);
            $nextIds[] = $nextId;
            $criteria->addNotInCondition('id', $nextIds);
        }
            
        $criteria->order = 'name';
        $models = Workflow::model()->findAll($criteria);
        $this->result->processed('models', $models);
        return $this->result;
    }*/
    
    public function getListBySite($params)
    {
        $siteId = $this->getParam($params, 'site_id', 0);
        $criteria = new CDbCriteria();
        $criteria->compare('site_id', $siteId);
        $criteria->order = 'name';
        $models = Workflow::model()->findAll($criteria);
        $this->result->processed('models', $models);
        return $this->result;
    }
    
    public function findWorkflowIds($id, $type, $forceStart=false)
    {
        static $ids;
        if (is_null($ids) || $forceStart)
            $ids = array();
        $model = Workflow::model()->findByPk($id);
        if (is_object($model) && $model->{$type}) {
            $ids[] = $model->{$type};
            $this->findWorkflowIds($model->{$type}, $type);
        }
        return $ids;
    }
    
    public function getLiveBySiteId($params)
    {
        $siteId = $this->getParam($params, 'id', 0);
        if (!$siteId)
            return $this->result->fail(ERROR_INVALID_DATA, Yii::t('Cms.Workflow','Invalid Site ID.'));
        
        $model = Workflow::model()->findByAttributes(array('site_id'=>$siteId, 'name'=>'Live'));
        $this->result->processed('model', $model);
        return $this->result;
    }
    
    public function getByUrl($params)
    {
        $url = $this->getParam($params, 'url', '');
        
        $model = null;
        if (empty($url) == false)
            $model = Workflow::model()->findByAttributes(array('url'=>$url));
        
        $this->result->processed('model', $model);
        return $this->result;
    }
    
    /**
    * Get a SiteUrl model given its ID
    * 
    * @param int id SiteUrl ID
    * @return FServiceModel
    */
    public function getBySite($params){
        $models = Workflow::model()->findAllByAttributes(array('site_id'=>$this->getParam($params, 'site_id',0)));
        $this->result->processed('models', $models);
        return $this->result;
    }
    
    public function getFinalWorkflowBySiteId($params)
    {
        $siteId = $this->getParam($params, 'site_id', 0);
        if (!$siteId)
            return $this->result->fail(ERROR_INVALID_DATA, Yii::t('Cms.Workflow','Invalid Site ID.'));
        
        $model = Workflow::model()->findByAttributes(array('site_id'=>$siteId, 'type'=>Workflow::TYPE_FINAL));
        $this->result->processed('model', $model);
        return $this->result;
    }
    
    public function getInitialWorkflowBySiteId($params)
    {
        $siteId = $this->getParam($params, 'site_id', 0);
        if (!$siteId)
            return $this->result->fail(ERROR_INVALID_DATA, Yii::t('Cms.Workflow','Invalid Site ID.'));
        
        $model = Workflow::model()->findByAttributes(array('site_id'=>$siteId, 'type'=>Workflow::TYPE_INITITAL));
        $this->result->processed('model', $model);
        return $this->result;
    }
    
    public function lookup($params)
    {
        $app = Yii::app();
        $deaultHost = parse_url($app->request->hostInfo, PHP_URL_HOST);
        
        $pathInfo = $app->request->getPathInfo();
        
        /*$env = '';
        //detect env dev
        if (stripos($pathInfo, 'dev/') === 0)
        {
            $env = 'dev/';
            $pathInfo = substr($pathInfo, 4);
        }*/
            
        $locale = substr($pathInfo,0,5);
        $localeId = str_replace('/','_',$locale);
        
        if ($app->localeManager->isLocaleIdValid($localeId))
            $deaultHost = $deaultHost.'/'.$locale;
        
        $host = $this->getParam($params, 'host', $deaultHost);
        
        // find the workflow from URI host info
        $model = null;
        $result = FSM::_run('Cms.workflow.getByUrl', array('url'=>$host));
        try {
            // if not fall to the catch the we found the workflow
            $model = $result->model;
        }
        catch (Exception $e)
        {
             // no workflow configured for the requested URI, 
             // possible to run the LIVE if domain is parked
        }
        
        if (!is_object($model)) {
            // workflow not found, check if domain is parked
            $criteria = new CDbCriteria();
            $criteria->compare('url',$host, true);
            $siteUrl = SiteUrl::model()->find($criteria);
            if (is_object($siteUrl))
            {
                Yii::app()->cmsManager->site = $siteUrl->site->attributes;
                // OK, domain is parked, find final workflow
                $model = Workflow::model()->findByAttributes(array(
                    'site_id'=>$siteUrl->site_id,
                    'type'=>Workflow::TYPE_FINAL,
                ));
            }
        }
        
        if (!is_object($model)) // no live workflow, die !!!
            $this->result->fail(ERROR_INVALID_DATA, 'Oups, looks like the domain is not configured properly to work with our CMS.');
        else
            Yii::app()->cmsManager->Workflow = $model->attributes;
        
        $this->result->processed('model', $model);
        return $this->result;
    }
    
    /**
    * delete all site url by site id
    * 
    * @param array $params
    * @return FServiceModel
    */
    public function deleteBySite($params)
    {
        $siteId = $this->getParam($params, 'site_id', 0);
        if ($siteId)
        {
            Workflow::model()->deleteAllByAttributes(array('site_id'=>$siteId));
        }
        
        return $this->result;
    }
    
    public function activePageSameWorkflow($params)
    {
        $sourceWorkflowId = $this->getParam($params, 'source_workflow_id', 0);
        $targetWorkflowId = $this->getParam($params, 'target_workflow_id', 0);
        
        $command = Yii::app()->getDb()->createCommand();
        $rows = $command->select()
            ->from(SITE_TABLE_PREFIX.'page_current_revision')
            ->where('workflow_id=:id', array(':id'=>$targetWorkflowId))
            ->queryAll();
        if (count($rows))
        {
            foreach ($rows as $row)
            {
                $command->reset();
                $exist = $command->select('COUNT(*)')
                    ->from(SITE_TABLE_PREFIX.'page_current_revision')
                    ->where('page_id=:page_id AND revision=:revision AND workflow_id=:workflow_id',
                        array(
                            ':page_id'=>(int) $row['page_id'],
                            ':revision'=>$row['revision'],
                            ':workflow_id'=>$sourceWorkflowId,
                        )
                    )
                    ->queryScalar();
                if (!$exist)
                {
                    $command->insert(SITE_TABLE_PREFIX.'page_current_revision', array(
                        'page_id'=>$row['page_id'],
                        'revision'=>$row['revision'],
                        'workflow_id'=>$sourceWorkflowId,
                    ));
                }
            }
        }
        return $this->result;
    }
    
    public function findByPage($params)
    {
        $pageId = $this->getParam($params, 'page_id', 0);
        $revisionId = $this->getParam($params, 'revision_id', 0);
        
        $criteria = new CDbCriteria();
        $criteria->join = 'INNER JOIN '.SITE_TABLE_PREFIX.'page_current_revision pcr ON pcr.workflow_id = t.id';
        $criteria->compare('pcr.page_id', $pageId);
        $criteria->compare('pcr.revision', $revisionId);
        $model = Workflow::model()->find($criteria);
        
        return $this->result->processed('model', $model);
    }
    
    public function isActiveInLive($params)
    {
        $pageId = $this->getParam($params, 'page_id', 0);
        
        $criteria = new CDbCriteria();
        $criteria->join = 'INNER JOIN '.SITE_TABLE_PREFIX.'page_current_revision pcr ON pcr.workflow_id = t.id';
        $criteria->compare('pcr.page_id', $pageId);
        $criteria->compare('t.type', Workflow::TYPE_FINAL);
        $status = Workflow::model()->exists($criteria);
        
        return $this->result->processed('status', $status);
    }
    
    public function findWorkflowBySNAndWN($params)
    {
        $siteName = $this->getParam($params, 'site_name', '');
        $workflowName = $this->getParam($params, 'workflow_name', '');
        $url = '';
        
        $criteria = new CDbCriteria();
        $criteria->with = array(
            'site'=>array(
                'select'=>false,
            )
        );
        $criteria->compare('site.name', $siteName);
        $criteria->addSearchCondition('t.name',$workflowName, true, 'AND', 'LIKE');
        $workflow = Workflow::model()->find($criteria);
        if (is_object($workflow))
        {
            $url = $workflow->url;
            if (strpos($url, 'http://') === false)
            {
                $url = 'http://'.$url;
            }
        }
        
        return $this->result->processed('url', $url);
    }
    
    public function activePage($params)
    {
        $workflowId = $this->getParam($params, 'workflow_id', 0);
        $pageId = $this->getParam($params, 'page_id', 0);
        $revision = $this->getParam($params, 'revision_id', 0);
        
        $command = Yii::app()->db->createCommand();
        
        if ($revision <= 0)
        {
            $command->delete(SITE_TABLE_PREFIX.'page_current_revision', 'page_id=:page_id AND workflow_id=:workflow_id', array(
                'page_id'=>$pageId,
                'workflow_id'=>$workflowId,
            ));
        }
        else
        {
            $exist = $command->select('COUNT(*)')
                ->from(SITE_TABLE_PREFIX.'page_current_revision')
                ->where('page_id=:page_id AND workflow_id=:workflow_id', array(
                    'page_id'=>$pageId,
                    'workflow_id'=>$workflowId,
                ))
                ->queryScalar();
            if ($exist)
            {
                $command->update(SITE_TABLE_PREFIX.'page_current_revision', array(
                    'revision'=>$revision,
                ), 'page_id=:page_id AND workflow_id=:workflow_id', array(
                    'page_id'=>$pageId,
                    'workflow_id'=>$workflowId,
                ));
            }
            else
            {
                $command->insert(SITE_TABLE_PREFIX.'page_current_revision', array(
                    'page_id'=>$pageId,
                    'workflow_id'=>$workflowId,
                    'revision'=>$revision,
                ));
            }
        }
    }
}
